let redis = require('../dao/redis');
let conf = require('../config/config');
let userDao = require('../dao/userDao');
let payAcctDao = require('../dao/payAcctDao');
let exchangeConfigDao = require('../dao/exchangeConfigDao');
let assert = require('assert');

const { BusiError, SysError } = require('../exception/exception');
const mysqlPool = require('../dao/MySQLPool');

let redisConst = require('../const/redisConst');
let axi = require('axios');
let apollo = require('../config/apollo');
let userService = require('./userService');

let cmService = module.exports;

let axios = null;

cmService.getAxios = async function(){
    if(!axios){
        let conf = await apollo.getConfig();
        
        const config = {
            timeout: 1500,
            baseURL: conf["commission.url"]
        };

        axios = axi.create(config);
    }

    return axios;
};

/**
 * 
 */
cmService.directQuery = async function(cond){
    let user = await userDao.getUserByUid(cond.uid);
    if (!user) {
        console.logw("getUserByUid err: user is null", cond.uid);
        throw new BusiError(500, "getUserByUid err: user is null");
    }

    if (user.isAgent !== 1){
        throw new BusiError(500, "玩家不是代理");
    }

    if (!user.code) {
        user.code = user.uid;
    }

    try {
        // 
        let res = await (await this.getAxios()).post("/pf/directQuery", {
            acctId: user.uid,
            typeCode: user.code, 
            page: cond.page,
            pageSize: 10,
            cAcctId: cond.cAcctId,
            registerTime: cond.registerTime
        });

        let data = res.data;
        if (data.code === "200000") {
            if(data.data.cnt > 0){
                for(let i = 0; i < data.data.cnt; i++){
                    let item = data.data.ds[i];
                    let u = await userDao.getUserByUid(item.directAcctID);
                    if (u) delete u.password;
                    data.data.ds[i].user = u;
                }
            }
            return data.data;
        }else{
            throw data.msg;
        }
    }catch(e){
        console.logw("POST /pf/directQuery err:", e.message, e.response);
            throw "homeStat err";
    }
};

/**
 * 
 */
cmService.directPerfQuery = async function(cond){
    let user = await userDao.getUserByUid(cond.uid);
    if (!user) {
        console.logw("getUserByUid err: user is null", cond.uid);
        throw new BusiError(500, "getUserByUid err: user is null");
    }

    if (user.isAgent !== 1){
        throw new BusiError(500, "玩家不是代理");
    }

    if (!user.code) {
        user.code = user.uid;
    }

    try {
        // 
        let res = await (await this.getAxios()).post("/pf/directPerfQuery", {
            acctId: user.uid,
            typeCode: user.code, 
            page: cond.page,
            pageSize: 10,
            cAcctId: cond.cAcctId,
            registerTime: cond.registerTime
        });

        let data = res.data;
        if (data.code === "200000") {
            if(data.data.cnt > 0){
                for(let i = 0; i < data.data.cnt; i++){
                    let item = data.data.hs[i];
                    let u = await userDao.getUserByUid(item.acctId);
                    if (u) delete u.password;
                    data.data.hs[i].user = u;
                }
            }
            return data.data;
        }else{
            throw data.msg;
        }
    }catch(e){
        console.logw("POST /pf/directPerfQuery err:", e.message, e.response);
            throw "homeStat err";
    }
};

/**
 * 上级查询
 * @param {String} uid
 * @returns {Promise<void>}
 */
cmService.homeStat = async function(uid) {
    let user = await userDao.getUserByUid(uid);
    if (!user) {
        console.logw("getUserByUid err: user is null", uid);
        throw new BusiError(500, "getUserByUid err: user is null");
    }

    if (user.isAgent !== 1){
        throw new BusiError(500, "玩家不是代理");
    }

    if (!user.code) {
        user.code = user.uid;
    }

    let url = await userService.getPromoteLink(uid);

    try {
        // 
        let res = await (await this.getAxios()).post("/pf/homeStat", {
            acctId: user.uid,
            typeCode: user.code
        });

        let data = res.data;
        if (data.code === "200000") {
            data.data.uid = user.uid;
            data.data.url = url;
            return data.data;
        }else{
            throw data.msg;
        }
    }catch(e){
        console.logw("POST /pf/homeStat err:", e.message, e.response);
            throw "homeStat err";
    }
};

// /pf/directStat

cmService.directStat = async function(uid) {
    let user = await userDao.getUserByUid(uid);
    if (!user) {
        console.logw("getUserByUid err: user is null", uid);
        throw new BusiError(500, "getUserByUid err: user is null");
    }

    if (user.isAgent !== 1){
        throw new BusiError(500, "玩家不是代理");
    }

    if (!user.code) {
        user.code = user.uid;
    }

    try {
        // 
        let res = await (await this.getAxios()).post("/pf/directStat", {
            acctId: user.uid,
            typeCode: user.code
        });

        let data = res.data;
        if (data.code === "200000") {
            return data.data;
        }else{
            throw data.msg;
        }
    }catch(e){
        console.logw("POST /pf/directStat err:", e.message, e.response);
            throw "directStat err";
    }
};

/**
 * 上级查询
 * @param {{uid: String, name: String, phone: String, acctId: String, page: Number}} cond
 * @returns {Promise<void>}
 */
cmService.groupParentQuery = async function (cond) {
    if (!cond.uid) {
        throw "uid must not be null";
    }

    let user = await userDao.getUserByUid(cond.uid);
    if (!user) {
        console.logw("getUserByUid err: user is null", cond.uid);
        throw "getUserByUid err: user is null";
    }

    if (user.isAgent === 1 && !user.code) {
        user.code = user.uid;
    }

    if (!user.code) {
        console.logw("getUserByUid err: user.code is null", cond.uid);
        throw "getUserByUid err: user.code is null";
    }

    let params = {};
    let flag = false;
    if (cond.name) {
        flag = true;
        params.name = cond.name;
    }
    if (cond.phone) {
        flag = true;
        params.phone = cond.phone;
    }

    if (cond.acctId){
        flag = true;
        params.uid = cond.acctId;
    }

    let uids = [];
    if (flag) {
        let users = await userDao.queryByCond(params);
        if (!users || users.length === 0) {
            console.logw("queryByCond err: users is null", params);
            throw "queryByCond err: users is null";
        }

        for (let i = 0; i < users.length; i++) {
            uids.push(users[i].uid);
        }
    }

    try {
        let res = await (await this.getAxios()).post("/mlr/queryParentNode", {
            acctId: user.uid,
            typeCode: user.code,
            pAcctIds: uids,
            page: cond.page,
            flag: "true"
        });

        let data = res.data;
        let resMap = {};
        if (data.code === "200000") {
            for (let i = 0; i < data.data.data.length; i++) {
                let item = data.data.data[i];
                let userInfo = await userDao.getUserInfoByUid(item.acctId);
                item.userInfo = userInfo;
            }
        }else{
            throw data.msg;
        }

        return data.data;
    }catch (e) {
        console.logw("POST /mlr/queryParentNode err:", e.message, e.response);
        throw "groupChildQuery err";
    }
};

/**
 * 下级查询
 * @param cond
 * @returns {Promise<void>}
 */
cmService.groupChildQuery = async function (cond) {
    if (!cond.uid) return null;

    let user = await userDao.getUserByUid(cond.uid);
    if (!user) {
        console.logw("getUserByUid err: user is null", cond.uid);
        throw "getUserByUid err: user is null";
    }

    if (user.isAgent === 1 && !user.code) {
        user.code = user.uid;
    }

    if (!user.code) {
        console.logw("getUserByUid err: user.code is null", cond.uid);
        throw "getUserByUid err: user.code is null";
    }

    let params = {};
    let flag = false;
    if (cond.name) {
        flag = true;
        params.name = cond.name;
    }
    if (cond.phone) {
        flag = true;
        params.phone = cond.phone;
    }

    if (cond.acctId){
        flag = true;
        params.uid = cond.acctId;
    }

    let uids = [];
    if (flag) {
        let users = await userDao.queryByCond(params);
        if (!users || users.length === 0) {
            console.logw("queryByCond err: users is null", params);
            throw "queryByCond err: users is null";
        }

        for (let i = 0; i < users.length; i++) {
            uids.push(users[i].uid);
        }
    }

    try {
        let res = await (await this.getAxios()).post("/mlr/queryChildNode", {
            acctId: user.uid,
            typeCode: user.code,
            cAcctIds: uids,
            page: cond.page,
            pAcctId: cond.pAcctId
        });

        let data = res.data;
        if (data.code === "200000") {
            for (let i = 0; i < data.data.data.length; i++) {
                let item = data.data.data[i];
                let userInfo = await userDao.getUserInfoByUid(item.acctId);
                item.userInfo = userInfo;
            }
        }else{
            throw data.msg;
        }

        return data.data;
    }catch (e) {
        console.logw("POST /mlr/queryChildNode err:", e.message, e.response);
        throw "groupChildQuery err";
    }
};

cmService.groupQuery = async function (uid) {
    let cacheKey = redisConst.GROUP_STAT_CUR + ":" + uid;
    let ret = null; // await redis.get(cacheKey);
    if (!ret) {
        ret = {
            duCnt: 0,
            duCntWeek: 0,
            duCntMonth: 0,
            gCnt: 0,
            gCntWeek: 0,
            gCntMonth: 0
        };
        let user = await userDao.getUserByUid(uid);
        if (!user) {
            console.logw("getUserByUid err: user == null", uid);
            return ret;
        }
        let typeCode = user.code;
        if (user && (user.code || user.isAgent === 1)) {
            if (!user.code && user.isAgent === 1) {
                typeCode = user.uid;
            }

            try {
                let res = await (await this.getAxios()).post("/mlr/groupStat", {
                    acctId: uid + "",
                    typeCode: typeCode
                });

                let data = res.data;
                if (data.code === "200000") {
                    ret = data.data;
                }
            } catch (e) {
                console.logw("POST /pf/perfStatCurWeek err:", e.message, e.response);
            }
        }

        await redis.set(cacheKey, ret, 2 * 3600);
    }

    return ret;
};

cmService.perfQuery = async function (uid) {
    let cacheKey = redisConst.PERF_STAT_WEEK_CUR + ":" + uid;
    let ret = null;//await redis.get(cacheKey);
    if (!ret) {
        ret = {
            total: 0,
            du: 0,
            proxy: 0
        };

        let user = await userDao.getUserByUid(uid);
        if (!user) {
            console.logw("getUserByUid err: user == null", uid);
            return ret;
        }
        let typeCode = user.code;
        if (user && (user.code || user.isAgent === 1)) {
            if (!user.code && user.isAgent === 1) {
                typeCode = user.uid;
            }

            try {
                let res = await (await this.getAxios()).post("/pf/perfStatCurWeek", {
                    acctId: uid+"",
                    typeCode: typeCode
                });

                let data = res.data;
                if (data.code === "200000") {
                    let list = data.data;
                    for (let i = 0; i < list.length; i++) {
                        let item = list[i];
                        ret.total += item.perfAmt;
                        if (item.level === 0) {
                            ret.du += item.perfAmt;
                        }

                        if (item.level === 1) {
                            ret.proxy += item.perfAmt;
                        }
                    }
                }
            } catch (e) {
                console.logw("POST /pf/perfStatCurWeek err:", e.message, e.response);
            }
        }

        await redis.set(cacheKey, ret, 2 * 3600);
    }

    return ret;
};

/**
 * 收益查询
 * @param uid
 * @returns {Promise<*>}
 */
cmService.profQuery = async function (uid) {
    let cacheKey = redisConst.PROF_STAT_CUR + ":" + uid;
    let ret = null; // await redis.get(cacheKey);
    if (!ret) {
        ret = {
            left: 0,
            proxy: 0,
            total: 0
        };

        let user = await userDao.getUserByUid(uid);
        let typeCode = user.code;
        if (user && (user.code || user.isAgent === 1)) {
            if (!user.code && user.isAgent === 1) {
                typeCode = user.uid;
            }

            try {
                let res = await (await this.getAxios()).post("/ps/getUserProfitStat", {
                    acctId: uid + "",
                    typeCode: typeCode
                });

                let data = res.data;
                if (data.code === "200000") {
                    data = data.data;
                    ret.left = data.noWithdrawProfit;
                    ret.proxy = data.proxyProfit;
                    ret.total = data.totalProfit;
                }
            } catch (e) {
                console.logw("POST /ps/getUserProfitStat err:", e.message, e.response);
            }
        }

        await redis.set(cacheKey, ret, 2 * 3600);
    }

    return ret;
};

/**
 * 账号信息
 * @param uid
 * @returns {Promise<*>}
 */
cmService.getAcctInfo = async function(uid){
    let user = await userDao.getUserInfoByUid(uid);
    if (!user) {
        console.logw("getUserByUid err: user == null", uid);
        throw "no this acct info";
    }

    let typeCode = user.code;
    if (user && (user.code || user.isAgent === 1)) {
        if (!user.code && user.isAgent === 1) {
            typeCode = user.uid;
        }

        try {

            let res = await (await this.getAxios()).post("/acct/getAcctInfo", {
                acctId: uid + "",
                typeCode: typeCode
            });

            let data = res.data;
            let resMap = {};
            if (data.code === "200000") {
                let item = data.data;
                item.userInfo = user;
                return item;
            }
        } catch (e) {
            console.logw("POST /pf/perfStatCurWeek err:", e.message, e.response);
            throw "get acct info err";
        }
    }

    throw "no this acct info";
};

/**
 * 本周直属会员业绩查询
 * @param uid
 * @param page
 * @returns {Promise<*>}
 */
cmService.duPerfQuery = async function (uid, page) {
    let cacheKey = redisConst.PERF_STAT_WEEK_CUR_DU + ":" + uid + ":" + page;
    let ret = null; //await redis.get(cacheKey);
    if (!ret) {
        ret = {
            cnt: 0,
            data: []
        };

        let user = await userDao.getUserByUid(uid);
        if (!user) {
            console.logw("getUserByUid err: user == null", uid);
            return ret;
        }
        let typeCode = user.code;
        if (user && (user.code || user.isAgent === 1)) {
            if (!user.code && user.isAgent === 1) {
                typeCode = user.uid;
            }

            try {
                let res = await (await this.getAxios()).post("/pf/perfStatDuCurWeek", {
                    acctId: uid + "",
                    typeCode: typeCode,
                    page: page,
                    pageSize: 10
                });

                let data = res.data;
                let resMap = {};
                if (data.code === "200000") {
                    for (let i = 0; i < data.data.data.length; i++) {
                        let item = data.data.data[i];
                        let userInfo = await userDao.getUserInfoByUid(item.acctId);
                        item.userInfo = userInfo;
                    }
                    ret = data.data;
                }
            } catch (e) {
                console.logw("POST /pf/perfStatCurWeek err:", e.message, e.response);
            }
        }

        await redis.set(cacheKey, ret, 2 * 3600);
    }

    return ret;
};

/**
 * 提现查询
 AcctId    string `form:"acct_id"`
 TypeCode  string `form:"type_code"`
 FlowNo    string `form:"flow_no"`
 Status    *int64 `form:"status" validate:"exists"`
 StartTime string `form:"start_time"`
 EndTime   string `form:"end_time"`
 Page      *int64 `form:"page" validate:"exists"`
 * @param cond
 * @returns {Promise<void>}
 */
cmService.wdQuery = async function(cond) {
    let user = await userDao.getUserByUid(cond.uid);
    if (!user) {
        console.logw("getUserByUid err: user == null", cond.uid);
        throw "getUserByUid err: user == null";
    }
    let typeCode = user.code;
    if (user && (user.code || user.isAgent === 1)) {
        if (!user.code && user.isAgent === 1) {
            typeCode = user.uid;
        }

        cond.acctId = user.uid;
        cond.typeCode = typeCode;

        try {
            let res = await (await this.getAxios()).post("/wc/queryWCPage", cond);

            let data = res.data;
            let resMap = {};
            if (data.code === "200000") {
                let list = data.data.data;
                for (let i = 0; i < list.length; i++) {
                    let item = list[i];
                    let user = await userDao.getUserInfoByUid(item.acctId);
                    item.userInfo = user;
                }
                return data.data;
            }else{
                throw data.msg;
            }
        }catch (e) {
            console.logw("POST /wc/queryWCPage  err:", e.message, e.response);
            throw "POST err";
        }
    }

    throw "user is not agent";
};

/**
 * 发起提现
 * @param cond
 * @returns {Promise<*>}
 */
cmService.wd = async function(cond) {
    let user = await userDao.getUserByUid(cond.uid);
    if (!user) {
        console.logw("getUserByUid err: user == null", cond.uid);
        throw "getUserByUid err: user == null";
    }
    let typeCode = user.code;
    if (user && (user.code || user.isAgent === 1)) {
        if (!user.code && user.isAgent === 1) {
            typeCode = user.uid;
        }

        cond.acctId = user.uid;
        cond.typeCode = typeCode;

        // 查询卡号
        let payAcct = await payAcctDao.get({uid: cond.uid, type: cond.type});
        if (!payAcct) {
            console.logw("no this pay acct:", cond);
            throw "no this pay acct";
        }

        let exConfig = await exchangeConfigDao.getConfig(cond.type);
        if (!exConfig){
            console.logw("no this ex config:", cond);
            throw "no this ex config";
        }

        let rate = exConfig.rate;
        cond.cardNo = payAcct.acct_no;
        cond.feeRate = rate;
        try {
            let res = await (await this.getAxios()).post("/wc/withdrawCash", cond);
            let data = res.data;
            let resMap = {};
            if (data.code === "200000") {
                return data.msg;
            }else{
                throw data.msg;
            }
        }catch (e) {
            console.logw("POST /wc/withdrawCash  err:", e.message, e.response, cond.uid);
            throw "POST err";
        }
    }

    throw "user is not agent";
};

// saveOrder
/**
 *
 * @param cond
 *  cond.uid
 *  cond.amount
 * @returns {Promise<*>}
 */
cmService.saveOrder = async function(cond) {
    let user = await userDao.getUserByUid(cond.uid);
    if (!user) {
        console.logw("getUserByUid err: user == null", cond.uid);
        throw "getUserByUid err: user == null";
    }
    let typeCode = user.code;
    if (user && (user.code || user.isAgent === 1)) {
        if (!user.code && user.isAgent === 1) {
            typeCode = user.uid;
        }

        cond.acctId = user.uid;
        cond.typeCode = typeCode;
        let amount = Number(parseFloat(cond.amount).toFixed(4));
        cond.amount = amount;
        try {
            let res = await (await this.getAxios()).post("/od/saveOrder", cond);
            let data = res.data;
            let resMap = {};
            if (data.code === "200000") {
                return data.msg;
            }else{
                throw data.msg;
            }
        }catch (e) {
            console.logw("POST /od/saveOrde  err:", e.message, e.response, cond.uid);
            throw "POST err";
        }
    }

    throw "user is not agent: " + cond.uid;
};

/**
 *
 * @param {{acctId:String}}cond
 * @returns {Promise<*>}
 */
cmService.addRoot = async function(cond) {
    let user = await userDao.getUserByUid(cond.acctId);
    if (!user) {
        console.logw("getUserByUid err: user == null", cond.acctId);
        throw "getUserByUid err: user == null";
    }

    cond.typeCode = user.uid;
    try {
        let res = await (await this.getAxios()).post("/mlr/addRootNode", cond);
        let data = res.data;
        let resMap = {};
        if (data.code === "200000") {
            await mysqlPool.doWithTx(async(conn) => {
                let res = await userDao.setUserToAgentWithTx(conn, cond.acctId);
                assert(res > 0, "set user to agent err: res <= 0");
                let res1 =  await userDao.setUserAgentCodeWithTx(conn, cond.acctId, data.data.typeCode);
                assert(res1 > 0, "set user agent code err: res1 <= 0");
            });
            return data.msg;
        }else{
            throw new BusiError(500, data.msg);
        }
    }catch (e) {
        console.logw("POST /mlr/addRootNode err:", e.message, e.response, cond.acctId);
        throw "POST err";
    }
};

/**
 *
 * @param {{pAcctId: String, acctId: String}} cond
 *
 * @returns {Promise<*>}
 */
cmService.addChild = async function(cond) {
    let user = await userDao.getUserByUid(cond.pAcctId);
    if (!user) {
        console.logw("getUserByUid err: user == null, puid:", cond.pAcctId);
        throw  new BusiError(500, "getUserByUid err: user == null");
    }

    // 不是代理用户不能推广
    if (user.isAgent !== 1) {
        console.logw("getUserByUid err: user is not agent!");
        throw new BusiError(500, "getUserByUid err: user is not agent!");
    }

    let curUser = await userDao.getUserByUid(cond.acctId);
    if (!curUser) {
        console.logw("getUserByUid err: user == null", cond.acctId);
        throw new BusiError(500, "getUserByUid err: user == null");
    }

    let typeCode = user.code;
    if (!typeCode||typeCode === ""){
        typeCode = user.uid;
    }

    cond.typeCode = typeCode;
    cond.acctId = curUser.uid;
    cond.pAcctId = user.uid;
    try {
        let res = await (await this.getAxios()).post("/mlr/addChildNodeByPAcct", cond);
        let data = res.data;
        let resMap = {};
        if (data.code === "200000") {
            await mysqlPool.doWithTx(async(conn) => {
                await userDao.setUserToAgentWithTx(conn, cond.pAcctId);
                let res1 =  await userDao.setUserAgentCodeWithTx(conn, cond.acctId, cond.typeCode);
                if (res1 < 1)
                    throw new BusiError(500, "set user agent code err: res1 <= 0");
            });
            return data.msg;
        }else{
            throw new BusiError(500, data.msg);
        }
    }catch (e) {
        console.logw("POST /mlr/addChildNodeByPAcct err:", e.message, e.response, cond.acctId);
        throw new BusiError(500, "POST err");
    }
};

/**
 * @param {{typeCode: String, acctId: String}} cond
 */
cmService.setUserToAgent = async function(cond){
    // /acct/setAcctToAgent
};

